/*
 * gramar.h
 *
 *  Created on: Mar 29, 2015
 *      Author: silivas
 */

#ifndef SRC_GRAMAR_H_
#define SRC_GRAMAR_H_

#include <iterator>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include <fstream>
#include "rule_collection.h"
#include "stringop.h"
#include "nrand.h"
//#include "word.h"
using namespace std;
class Grammar {
public:
	void gen_aux(Word& word, vector<string>& ret) {
		if (!word.isbracketed()) {
			ret.push_back(word.toString());
		} else {
			//fetch the possible rules
			Rule_Collection& rc = (*this)[word.toString()];
			//select on at random
			Rule& r = rc[(vector<Rule>::size_type)nrand(rc.size())];
			//expand the selected rule
			for(int i=0; i<r.size(); i++){
				gen_aux(r[i], ret);
			}
		}
	}
	vector<string> gen_sentence() {
		vector<string> ret;
		Word word("<sentence>");
		gen_aux(word, ret);
		return ret;
	}
	void add_category(const string& category) {
		vector<string> vec = split(category);
		if (!vec.empty())
			_collections[vec[0]].add_rule(vec.begin() + 1, vec.end());
	}

	Rule_Collection& operator[](const string& skey) {
		map<string, Rule_Collection>::iterator it = _collections.find(skey);
		if (it != _collections.end())
			return (_collections.find(skey)->second);
		else
			throw logic_error("empty rule");
	}

	Grammar(const string& filename) {
		ifstream infile(filename);
		string line;
		while (getline(infile, line)) {
			add_category(line);
		}
	}
	Grammar() = default;
private:
	map<string, Rule_Collection> _collections;
};

#endif /* SRC_GRAMAR_H_ */
